/*
 * Copyright (c) 2022 PATEO CONNECT+ (Nanjing) Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "voice_assistant_callback_event_target.h"
#include "voice_assistant_log.h"

namespace OHOS {
namespace CarVoiceAssistant {

    void VoiceAssistantCallbackEventTarget::AddListener(sptr<IVoiceAssistantClientCallback> proxy, sptr<VoiceAssistantClientCallbackDeathRecipient> deathRecipient)
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::addListener");
        listenerList_.push_back({ proxy, deathRecipient });
    }

    void VoiceAssistantCallbackEventTarget::RemoveListener(const wptr<IRemoteObject>& remote)
    {
        listenerList_.remove_if([remote](VoiceAssistantCallbackEventListener listener) -> bool {
            if (listener.proxy_ == nullptr) {
                return false;
            }
            sptr<IRemoteObject> object = listener.proxy_->AsObject();
            if (object != nullptr && remote == object) {
                if (listener.deathRecipient_) {
                    object->RemoveDeathRecipient(listener.deathRecipient_);
                }
                return true;
            }

            return false;
        });
        VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::RemoveListener by remote:%{public}d", listenerList_.size());
    }

    void VoiceAssistantCallbackEventTarget::EmitOnWakeUp()
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::EmitOnWakeUp");
        DoEmit([](sptr<IVoiceAssistantClientCallback>& proxy) {
            proxy->NotifyWakeUp();
        });
    }

    void VoiceAssistantCallbackEventTarget::EmitRecognizeStateChanged(bool isRecognizing)
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::EmitRecognizeStateChanged:%{public}s", isRecognizing ? "true" : "false");
        DoEmit([isRecognizing](sptr<IVoiceAssistantClientCallback>& proxy) {
            proxy->NotifyRecognizeStateChanged(isRecognizing);
        });
    }

    void VoiceAssistantCallbackEventTarget::EmitAsrResult(std::string& result)
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::EmitFavoriteListChanged:%{public}s", result.c_str());
        DoEmit([result](sptr<IVoiceAssistantClientCallback>& proxy) {
            proxy->NotifyAsrResult(result);
        });
    }

    void VoiceAssistantCallbackEventTarget::EmitTTSPlayStateChanged(bool isPlaying){
                VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::EmitTTSPlayStateChanged:%{public}s", isPlaying ? "true" : "false");
        DoEmit([isPlaying](sptr<IVoiceAssistantClientCallback>& proxy) {
            proxy->NotifyTTSPlayStateChanged(isPlaying);
        });
    }

    template <typename Callback>
    void VoiceAssistantCallbackEventTarget::DoEmit(Callback callback)
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::DoEmit");
        for (std::list<VoiceAssistantCallbackEventListener>::iterator it = listenerList_.begin(); it != listenerList_.end(); ++it) {
            VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::DoEmit schedule");
            if (it->proxy_ == nullptr) {
                VOICE_ASSISTANT_LOGI("VoiceAssistantCallbackEventTarget::DoEmit:proxy_ is null");
                continue;
            } else {
                callback(it->proxy_);
            }
        }
    }

}
}
